package org.JWCB.friend.service.exam;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.JWCB.common.core.constants.UserConstants;
import org.JWCB.common.core.domain.vo.TableDataInfo;
import org.JWCB.common.core.enums.ResultCode;
import org.JWCB.common.core.exception.ServiceException;
import org.JWCB.common.core.utils.ThreadLocalUtil;
import org.JWCB.friend.aspect.CheckUserStatus;
import org.JWCB.friend.domain.exam.dto.ExamQueryDto;
import org.JWCB.friend.domain.exam.dto.ExamRankQueryDto;
import org.JWCB.friend.domain.exam.entity.Exam;
import org.JWCB.friend.domain.exam.vo.ExamFirstQuestionVo;
import org.JWCB.friend.domain.exam.vo.ExamListItemVo;
import org.JWCB.friend.domain.exam.vo.ExamRankListItemVo;
import org.JWCB.friend.domain.user.entity.UserExam;
import org.JWCB.friend.domain.user.vo.UserDetailVo;
import org.JWCB.friend.manager.ExamCacheManager;
import org.JWCB.friend.manager.UserCacheManager;
import org.JWCB.friend.mapper.exam.ExamMapper;
import org.JWCB.friend.mapper.user.UserExamMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;



@Slf4j
@Service
public class ExamService {

    @Value("${file.oss.downloadUrl}")
    private String downloadUrl;

    @Autowired
    private ExamMapper examMapper;

    @Autowired
    private ExamCacheManager examCacheManager;

    @Autowired
    private UserExamMapper userExamMapper;


    @Autowired
    private UserCacheManager userCacheManager;



    @Value("${file.oss.avatarDir}")
    private String avatarDir;
    /**
     * 从数据库中获取数据
     * @param examQueryDto 查询信息
     * @return 数据
     */
    private List<ExamListItemVo> listByDB(ExamQueryDto examQueryDto) {
        PageHelper.startPage(examQueryDto.getPageNum(),examQueryDto.getPageSize());
        return examMapper.selectExamList(examQueryDto);
    }


    /**
     * 查询数据
     * @param examQueryDto 查询信息
     * @return 数据
     */
    public TableDataInfo list(ExamQueryDto examQueryDto) {
        Long listSize = examCacheManager.getListSize(examQueryDto.getType(),null);
        List<ExamListItemVo> examListItemVos = null;
        if(listSize == null || listSize <= 0) {
            examListItemVos = listByDB(examQueryDto);
            examCacheManager.refreshCache(examQueryDto.getType(),null);
            listSize = new PageInfo<>(examListItemVos).getTotal();
        }else {
            examListItemVos = examCacheManager.getExamList(examQueryDto,null);
            listSize = examCacheManager.getListSize(examQueryDto.getType(),null);
        }
        if(CollectionUtil.isEmpty(examListItemVos)) {
            return TableDataInfo.empty();
        }
        assembleExamList(examListItemVos);
        return TableDataInfo.success(examListItemVos,listSize);
    }


    /**
     * 设置报名竞赛
     * @param examListItemVos 原竞赛列表
     */
    private void assembleExamList(List<ExamListItemVo> examListItemVos) {
        Long userId = ThreadLocalUtil.get(UserConstants.USER_ID,Long.class);
        if(userId == null) {
            // 用户未登录
            return;
        }
        List<Long> userExamIds = examCacheManager.getAllUserExam(userId);
        if(CollectionUtil.isEmpty(userExamIds)) {
            return;
        }
        for(ExamListItemVo examListItemVo : examListItemVos) {
            if(userExamIds.contains(examListItemVo.getExamId())) {
                examListItemVo.setRegistered(true);
            }
        }
    }


    /**
     * 获取竞赛中首道题目
     */
    @CheckUserStatus
    public ExamFirstQuestionVo firstQuestion(Long examId) {
        if(examId == null) {
            throw new ServiceException(ResultCode.FAILED_NOT_EXISTS);
        }
        Exam exam = examCacheManager.getExam(examId);
//        if(exam == null) {
//            throw new ServiceException(ResultCode.FAILED_NOT_EXISTS);
//        }
        if(exam.getStartTime().isAfter(LocalDateTime.now())) {
            throw new ServiceException(ResultCode.EXAM_NOT_START);
        }
        ExamFirstQuestionVo examFirstQuestionVo = new ExamFirstQuestionVo();
        examFirstQuestionVo.setTitle(exam.getTitle());
        examFirstQuestionVo.setEndTime(exam.getEndTime());
        long listSize = examCacheManager.getExamQuestionListSize(examId);
        if(listSize <= 0) {
            examCacheManager.refreshExamQuestionListCache(examId);
        }
        Long firstQuestionId =  examCacheManager.getFirstQuestion(examId);
        examFirstQuestionVo.setFirstQuestionId(firstQuestionId);
        return examFirstQuestionVo;
    }

    /**
     * 竞赛下一题
     */
    @CheckUserStatus
    public String nextQuestion(Long examId,Long questionId) {
        if(examId == null || questionId == null) {
            throw new ServiceException(ResultCode.FAILED);
        }
        long listSize = examCacheManager.getExamQuestionListSize(examId);
        if(listSize <= 0) {
            examCacheManager.refreshExamQuestionListCache(examId);
        }
        Long nextId = examCacheManager.getNextQuestionId(examId,questionId);
        return nextId.toString();
    }


    /**
     * 竞赛上一题
     */
    @CheckUserStatus
    public String prevQuestion(Long examId,Long questionId) {
        if(examId == null || questionId == null) {
            throw new ServiceException(ResultCode.FAILED);
        }
        long listSize = examCacheManager.getExamQuestionListSize(examId);
        if(listSize <= 0) {
            examCacheManager.refreshExamQuestionListCache(examId);
        }
        Long nextId = examCacheManager.getPrevQuestionId(examId,questionId);
        return nextId.toString();
    }


    /**
     * 查看竞赛排名信息
     */
    public TableDataInfo rankList(ExamRankQueryDto queryDto) {
        long listSize = examCacheManager.getExamRankListSize(queryDto.getExamId());
        List<ExamRankListItemVo> examRankListItemVoList;
        if(listSize <= 0) {
            List<UserExam> userExams = rankListByDB(queryDto);
            examRankListItemVoList = assembleExamRankList(userExams);
            listSize = new PageInfo<>(userExams).getTotal();
            examCacheManager.refreshExamRankList(queryDto.getExamId());
        }else {
            examRankListItemVoList = examCacheManager.getExamRankList(queryDto.getExamId(),queryDto.getPageSize(),queryDto.getPageNum());
            listSize = examCacheManager.getExamRankListSize(queryDto.getExamId());
        }
        if(CollectionUtil.isEmpty(examRankListItemVoList)) {
            return TableDataInfo.empty();
        }
        examRankListItemVoList = examRankListItemVoList.stream()
                .map(vo -> {
                    ExamRankListItemVo newVo = BeanUtil.copyProperties(vo, ExamRankListItemVo.class);
                    newVo.setHeadImage(downloadUrl + avatarDir + vo.getHeadImage());
                    return newVo;
                })
                .collect(Collectors.toList());
        return TableDataInfo.success(examRankListItemVoList,listSize);
    }


    private List<ExamRankListItemVo> assembleExamRankList(List<UserExam> userExams) {
        List<ExamRankListItemVo> examRankListItemVoList = new ArrayList<>();
        for (UserExam userExam : userExams) {
            Long userId = userExam.getUserId();
            UserDetailVo userDetailVo = userCacheManager.getUserInfo(userId);
            if(userDetailVo != null) {

                userDetailVo.setHeadImage(userDetailVo.getHeadImage());
                examRankListItemVoList.add(assembleSingleExamRankList(userDetailVo,userExam));
            }
        }
        return examRankListItemVoList;
    }

    private ExamRankListItemVo assembleSingleExamRankList(UserDetailVo userDetailVo,UserExam userExam) {
        ExamRankListItemVo rankListItemVo = new ExamRankListItemVo();
        rankListItemVo.setExamRank(userExam.getExamRank());
        rankListItemVo.setHeadImage(userDetailVo.getHeadImage());
        rankListItemVo.setNickName(userDetailVo.getNickName());
        rankListItemVo.setScore(userExam.getScore());
        return rankListItemVo;
    }

    /**
     * 从数据库获取
     */
    public List<UserExam> rankListByDB(ExamRankQueryDto queryDto) {
        PageHelper.startPage(queryDto.getPageNum(),queryDto.getPageSize());
        return userExamMapper.selectList(new LambdaQueryWrapper<UserExam>()
                .eq(UserExam::getExamId, queryDto.getExamId())
                .isNotNull(UserExam::getScore)
                .isNotNull(UserExam::getExamRank)
                .orderByAsc( UserExam::getExamRank));
    }







}
